﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;

namespace dotHTML {
    /// <summary>
    /// Convenience methods for writing paritcular types of attributes out to a
    /// StringBuilder instance in HTML format.
    /// </summary>
    public static class AttributeWriter {

        /// <summary>
        /// If e != null, appends 'attribName="e.ToString().ToLower()"' to sb.
        /// </summary>
        /// <param name="sb">A reference to the StringBuilder to write out
        /// to.</param>
        /// <param name="e">The parameter to write out.</param>
        /// <param name="attribName">The name of the attribute.</param>
        /// <param name="lowerCase">Determines whether or not to convert the
        /// resulting string data to lowercase.</param>
        public static void Write(StringBuilder sb, object e, string attribName,
            bool lowerCase) {
            if (e != null) {
                WriteAttributeName(sb, attribName);
                if (lowerCase) {
                    sb.Append(e.ToString().ToLower());
                } else {
                    sb.Append(e.ToString());
                }
                sb.Append('"');
            }
        }

        /// <summary>
        /// If e != null, appends 'attribName="e.ToString()"' to sb.
        /// </summary>
        /// <param name="sb">A reference to the StringBuilder to write out
        /// to.</param>
        /// <param name="e">The parameter to write out.</param>
        /// <param name="attribName">The name of the attribute.</param>
        public static void Write(StringBuilder sb, object e, string attribName) {
            Write(sb, e, attribName, false);
        }

        /// <summary>
        /// If b != null, appends 'attribName="b"' to sb.
        /// </summary>
        /// <param name="sb">A reference to the StringBuilder to write out
        /// to.</param>
        /// <param name="b">The parameter to write out.</param>
        /// <param name="attribName">The name of the attribute.</param>
        public static void Write(StringBuilder sb, bool? b,
            string attribName) {
            if (b != null) {
                WriteAttributeName(sb, attribName);
                sb.Append(b.ToString().ToLower());
                sb.Append('"');
            }
        }

        /// <summary>
        /// If b == true, appends 'attribName="attribName"' to sb.
        /// </summary>
        /// <param name="sb">A reference to the StringBuilder to write out
        /// to.</param>
        /// <param name="b">The parameter to write out.</param>
        /// <param name="attribName">The name of the attribute.</param>
        public static void Write(StringBuilder sb, bool b, string attribName) {
            if (b) {
                WriteAttributeName(sb, attribName);
                sb.Append(attribName);
                sb.Append('"');
            }
        }

        /// <summary>
        /// If coll != null, appends 'attribName="(collection, separated by
        /// spaces)"' to sb.
        /// </summary>
        /// <param name="sb">A reference to the StringBuilder to write out
        /// to.</param>
        /// <param name="coll">The parameter to write out.</param>
        /// <param name="attribName">The name of the attribute.</param>
        /// <param name="sep">The separator character to delimit with.</param>
        public static void Write(StringBuilder sb, ICollection<string> coll,
            string attribName, char sep) {
            if (coll.Count > 0) {
                WriteAttributeName(sb, attribName);
                foreach (string s in coll) {
                    sb.Append(s);
                    sb.Append(sep);
                }
                sb.Append('"');
            }
        }

        /// <summary>
        /// If coll != null, appends 'attribName="(collection, separated by
        /// spaces)"' to sb.
        /// </summary>
        /// <param name="sb">A reference to the StringBuilder to write out
        /// to.</param>
        /// <param name="coll">The parameter to write out.</param>
        /// <param name="attribName">The name of the attribute.</param>
        /// <param name="sep">The separator character to delimit with.</param>
        public static void Write(StringBuilder sb, ICollection<int> coll,
            string attribName, char sep) {
            if (coll.Count > 0) {
                WriteAttributeName(sb, attribName);
                foreach (int s in coll) {
                    sb.Append(s.ToString());
                    sb.Append(sep);
                }
                sb.Append('"');
            }
        }

        /// <summary>
        /// If coll != null, appends 'attribName="(collection, separated by
        /// spaces)"' to sb.
        /// </summary>
        /// <param name="sb">A reference to the StringBuilder to write out
        /// to.</param>
        /// <param name="coll">The parameter to write out.</param>
        /// <param name="attribName">The name of the attribute.</param>
        /// <param name="sep">The separator character to delimit with.</param>
        public static void Write(StringBuilder sb, ICollection<char> coll,
            string attribName, char sep) {
            if (coll.Count > 0) {
                WriteAttributeName(sb, attribName);
                foreach (char s in coll) {
                    sb.Append(s);
                    sb.Append(' ');
                }
                sb.Append('"');
            }
        }

        /// <summary>
        /// If i != null, appends 'attribName="(collection, separated by
        /// spaces)"' to sb.
        /// </summary>
        /// <param name="sb">A reference to the StringBuilder to write out
        /// to.</param>
        /// <param name="dict">The parameter to write out.</param>
        /// <param name="attribName">The name prefix of the attribute (e.g.
        /// "data-" for the "data-*" element).</param>
        public static void Write(StringBuilder sb,
            IDictionary<string, string> dict, string attribName) {
            if (dict.Count > 0) {
                foreach (KeyValuePair<string, string> kvp in dict) {
                    sb.Append(' ');
                    sb.Append(attribName);
                    sb.Append(kvp.Key);
                    sb.Append("=\"");
                    sb.Append(kvp.Value);
                    sb.Append('"');
                }
            }
        }

        /// <summary>
        /// If c != null, appends 'attribName="(HTML color code)"' to sb.
        /// </summary>
        /// <param name="sb">A reference to the StringBuilder to write out
        /// to.</param>
        /// <param name="c">The parameter to write out.</param>
        /// <param name="attribName">The name prefix of the attribute (e.g.
        /// "data-" for the "data-*" element).</param>
        public static void Write(StringBuilder sb, Color? c,
            string attribName) {
            if (c != null) {
                WriteAttributeName(sb, attribName);
                sb.Append('#');
                // cut off MSB (alpha value), leaving 24-bit HTML color code
                sb.Append((c.Value.ToArgb() & 0x00FFFFFF).ToString("X6"));
                sb.Append('"');
            }
        }

        /// <summary>
        /// If d != null, appends 'attribName="YYYY-MM-DDThh:mm:ssK"' to sb.
        /// </summary>
        /// <param name="sb">A reference to the StringBuilder to write out
        /// to.</param>
        /// <param name="d">The parameter to write out.</param>
        /// <param name="attribName">The name prefix of the attribute (e.g.
        /// "data-" for the "data-*" element).</param>
        public static void Write(StringBuilder sb, DateTime? d,
            string attribName) {
            if(d != null) {
                WriteAttributeName(sb, attribName);
                sb.Append(d.Value.ToString("YYYY-MM-DDThh:mm:ssK"));
                sb.Append('"');
            }
        }

        /// <summary>
        /// Writes out the attribute name in the form of 'attributeName="'.
        /// </summary>
        /// <param name="sb">A reference to the StringBuilder to write out
        /// to.</param>
        /// <param name="a">The name of the attribute.</param>
        private static void WriteAttributeName(StringBuilder sb, string a) {
            sb.Append(' ');
            sb.Append(a);
            sb.Append("=\"");
        }
    }
}
